using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Wax.Runner
{
    public partial class ResultsPanel : UserControl
    {
        #region Private fields

        /// <summary>
        /// Object that manages the loading and execution of tests
        /// </summary>
        private readonly TestRunner testRunner;

        #endregion


        #region Constructors

        public ResultsPanel(TestRunner testRunner)
        {
            this.testRunner = testRunner;
            this.testRunner.LoadComplete += new EventHandler(TestRunnerLoadComplete);
            this.testRunner.ExecutionStarted += new EventHandler(TestRunnerExecutionStarted);
            this.testRunner.ExecutionCompleted += new EventHandler(TestRunnerExecutionCompleted);
            this.testRunner.TestErrorOccured += new EventHandler<TestErrorEventArgs>(TestRunnerTestErrorOccured);
            InitializeComponent();

        }

        #endregion

        #region Public properties

        /// <summary>
        /// Displays the test item.
        /// </summary>
        /// <param name="test">The test.</param>
        public void DisplayTestItem(Test test)
        {
            this.listProperties.BeginUpdate();
            this.listProperties.Items.Clear();

            this.listProperties.Items.Add(new ListViewItem(new string[] { "Test Id", test.Id }));
            this.listProperties.Items.Add(new ListViewItem(new string[] { "No. of commands", test.Commands.Count.ToString() }));

            this.listProperties.EndUpdate();
        }

        /// <summary>
        /// Displays the command item.
        /// </summary>
        /// <param name="command">The command.</param>
        public void DisplayCommandItem(Command command)
        {
            this.listProperties.BeginUpdate();
            this.listProperties.Items.Clear();

            this.listProperties.Items.Add(new ListViewItem(new string[] { "Command Id", command.Id }));
            this.listProperties.Items.Add(new ListViewItem(new string[] { "Command type", command.CommandType.ToString() }));
            this.listProperties.Items.Add(new ListViewItem(new string[] { "Command arguments", GetCommandArgs(command.Arguments) }));
            this.listProperties.Items.Add(new ListViewItem(new string[] { "Find method", command.FindMethod.MethodType.ToString() }));
            this.listProperties.Items.Add(new ListViewItem(new string[] { "Find arguments", GetCommandArgs(command.FindMethod.Arguments) }));

            this.listProperties.EndUpdate();
        }

        #endregion

        #region Private static methods

        /// <summary>
        /// Gets the command args.
        /// </summary>
        /// <param name="arguments">The arguments.</param>
        /// <returns></returns>
        private static string GetCommandArgs(Collection<string> arguments)
        {
            string commandArgs = string.Empty;
            foreach (string argument in arguments)
            {
                commandArgs = commandArgs + argument + ", ";
            }

            if (!string.IsNullOrEmpty(commandArgs))
            {
                commandArgs = commandArgs.Substring(0, commandArgs.Length - 2);
            }
            return commandArgs;
        }

        #endregion

        #region Private instance methods

        #region User control events

        /// <summary>
        /// Handles the Resize event of the ResultsPanel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ResultsPanelResize(object sender, EventArgs e)
        {
            columnException.Width = this.Width - columnTest.Width - columnCommand.Width - 20;
        }

        /// <summary>
        /// Handles the DoubleClick event of the listProperties control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ListErrorsDoubleClick(object sender, EventArgs e)
        {
            ShowExceptionDialog();
        }

        /// <summary>
        /// Handles the KeyPress event of the listErrors control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.KeyPressEventArgs"/> instance containing the event data.</param>
        private void ListErrorsKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                this.ShowExceptionDialog();
            }
        }

        /// <summary>
        /// Handles the ExecutionCompleted event of the TestRunner control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TestRunnerExecutionCompleted(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler(TestRunnerExecutionCompleted), new object[] { sender, e });
                return;
            }

            if (this.listErrors.Items.Count > 0)
            {
                this.tabControl.SelectedTab = this.tabResults;
            }
        }

        /// <summary>
        /// Handles the TestErrorOccurred event of the testRunner control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Wax.TestErrorEventArgs"/> instance containing the event data.</param>
        private void TestRunnerTestErrorOccured(object sender, TestErrorEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler<TestErrorEventArgs>(TestRunnerTestErrorOccured), new object[] { sender, e });
                return;
            }

            ListViewItem item = new ListViewItem();
            item.Text = e.Error.Test.Id;
            item.SubItems.Add(e.Error.Command.Id);
            item.SubItems.Add(e.Error.Exception.ToString());
            item.Tag = e.Error;
            listErrors.Items.Add(item);
        }


        /// <summary>
        /// Handles the LoadComplete event of the testRunner control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void TestRunnerLoadComplete(object sender, EventArgs e)
        {
            this.listErrors.BeginUpdate();
            this.listErrors.Items.Clear();
            this.listErrors.EndUpdate();

            this.tabControl.SelectedTab = this.tabProperties;
        }


        /// <summary>
        /// Handles the ExecutionStarted event of the testRunner control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TestRunnerExecutionStarted(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EventHandler(TestRunnerExecutionStarted), new object[] { sender, e });
                return;
            }

            this.listErrors.Items.Clear();
        }

        /// <summary>
        /// Shows the exception dialog.
        /// </summary>
        private void ShowExceptionDialog()
        {
            if (this.listErrors.SelectedItems.Count > 0)
            {
                TestError testError = listErrors.SelectedItems[0].Tag as TestError;

                if (testError != null)
                {
                    ExceptionDialog exceptionDialog = new ExceptionDialog(testError);
                    exceptionDialog.ShowDialog(this);
                }
            }
        }
        #endregion        
        
        #endregion      
    }
}
